from flask import Blueprint, render_template, request, jsonify, redirect, url_for, flash, send_file, Response
import json
import os
import re
import importlib
import sys
from datetime import date, datetime, timedelta
from config_params import params, shift_config, three_shift_params, shift_control, shift_mode_config, rest_time_control
from .models import (
    ScheduleResult,
    Elderdemand,
    TimeSlot,
    DicNursingAction,
    Attendantskills,
    CaregiverSchedule,
    ShiftAssignment,
    db,
)
from sqlalchemy import func, desc
import pandas as pd
import io

# 创建前端页面蓝图
views_page = Blueprint('views_page', __name__, template_folder='templates')

@views_page.route('/')
def index():
    """主页面，显示所有可用的接口页面"""
    return render_template('index.html')

@views_page.route('/generate_schedule_page')
def generate_schedule_page():
    """生成排班页面"""
    return render_template('generate_schedule.html')

@views_page.route('/view_schedule_page')
def view_schedule_page():
    """查看排班页面"""
    elders = Elderdemand.query.filter_by(arrange="1").all()
    return render_template('view_schedule.html', elders=elders)

@views_page.route('/nursing_actions_page')
def nursing_actions_page():
    """护理动作页面"""
    actions = DicNursingAction.query.all()
    return render_template('nursing_actions.html', actions=actions)

@views_page.route('/elders_page')
def elders_page():
    """老人信息页面"""
    elders = Elderdemand.query.filter_by(arrange="1").all()
    return render_template('elders.html', elders=elders)

@views_page.route('/caregivers_page')
def caregivers_page():
    """护理员信息页面"""
    caregivers = Attendantskills.query.all()
    return render_template('caregivers.html', caregivers=caregivers)

@views_page.route('/three_shift_schedule_page')
def three_shift_schedule_page():
    """三班制排班页面"""
    elders = Elderdemand.query.filter_by(arrange="1").all()
    caregivers = Attendantskills.query.all()

    # 限制数据量，提高页面加载速度
    elders = elders[:10] if len(elders) > 10 else elders
    caregivers = caregivers[:10] if len(caregivers) > 10 else caregivers

    # 获取最新的排班结果
    latest_results = ScheduleResult.query.order_by(
        ScheduleResult.schedule_date.desc()
    ).limit(5).all()

    return render_template(
        'three_shift_schedule.html',
        elders=elders,
        caregivers=caregivers,
        latest_results=latest_results,
        three_shift_params=three_shift_params,
        shift_config=shift_config,
        shift_control=shift_control,
        shift_mode_config=shift_mode_config,
        rest_time_control=rest_time_control
    )

@views_page.route('/simple_three_shift_schedule_page')
def simple_three_shift_schedule_page():
    """简化版三班制排班页面"""
    elders = Elderdemand.query.filter_by(arrange="1").all()
    caregivers = Attendantskills.query.all()

    # 限制数据量，提高页面加载速度
    elders = elders[:10] if len(elders) > 10 else elders
    caregivers = caregivers[:10] if len(caregivers) > 10 else caregivers

    return render_template(
        'simple_three_shift_schedule.html',
        elders=elders,
        caregivers=caregivers,
        three_shift_params=three_shift_params,
        shift_config=shift_config,
        shift_control=shift_control,
        shift_mode_config=shift_mode_config,
        rest_time_control=rest_time_control
    )

@views_page.route('/config_params_page', methods=['GET', 'POST'])
def config_params_page():
    """配置参数页面"""
    if request.method == 'POST':
        try:
            # 获取表单数据
            param_type = request.form.get('param_type')
            param_name = request.form.get('param_name')
            param_value = request.form.get('param_value')

            # 根据参数类型更新相应的参数
            if param_type == 'params':
                update_param(params, param_name, param_value)
            elif param_type == 'shift_config':
                update_nested_param(shift_config, param_name, param_value)
            elif param_type == 'three_shift_params':
                update_param(three_shift_params, param_name, param_value)
            elif param_type == 'shift_control':
                update_param(shift_control, param_name, param_value)
            elif param_type == 'shift_mode_config':
                update_nested_param(shift_mode_config, param_name, param_value)
            elif param_type == 'rest_time_control':
                update_nested_param(rest_time_control, param_name, param_value)

            # 更新配置文件
            update_config_file()

            # 返回成功消息
            return jsonify({'success': True, 'message': f'参数 {param_name} 已更新为 {param_value}'})
        except Exception as e:
            # 返回错误消息
            return jsonify({'success': False, 'message': f'更新参数失败: {str(e)}'})

    return render_template(
        'config_params.html',
        params=params,
        shift_config=shift_config,
        three_shift_params=three_shift_params,
        shift_control=shift_control,
        shift_mode_config=shift_mode_config,
        rest_time_control=rest_time_control
    )

@views_page.route('/get_param', methods=['GET'])
def get_param():
    """获取单个参数的值"""
    try:
        param_type = request.args.get('param_type')
        param_name = request.args.get('param_name')

        if not param_type or not param_name:
            return jsonify({'success': False, 'message': '参数类型和参数名不能为空'})

        # 根据参数类型获取相应的参数值
        if param_type == 'params':
            if param_name not in params:
                return jsonify({'success': False, 'message': f'参数 {param_name} 不存在'})
            return jsonify({'success': True, 'value': params[param_name]})
        elif param_type == 'shift_config':
            # 解析参数路径
            path_parts = param_name.split('.')
            current_dict = shift_config
            for part in path_parts:
                if part not in current_dict:
                    return jsonify({'success': False, 'message': f'参数 {param_name} 不存在'})
                current_dict = current_dict[part]
            return jsonify({'success': True, 'value': current_dict})
        elif param_type == 'three_shift_params':
            if param_name not in three_shift_params:
                return jsonify({'success': False, 'message': f'参数 {param_name} 不存在'})
            return jsonify({'success': True, 'value': three_shift_params[param_name]})
        elif param_type == 'shift_control':
            if param_name not in shift_control:
                return jsonify({'success': False, 'message': f'参数 {param_name} 不存在'})
            return jsonify({'success': True, 'value': shift_control[param_name]})
        elif param_type == 'shift_mode_config':
            # 解析参数路径
            path_parts = param_name.split('.')
            current_dict = shift_mode_config
            for part in path_parts:
                if part not in current_dict:
                    return jsonify({'success': False, 'message': f'参数 {param_name} 不存在'})
                current_dict = current_dict[part]
            return jsonify({'success': True, 'value': current_dict})
        elif param_type == 'rest_time_control':
            # 解析参数路径
            path_parts = param_name.split('.')
            current_dict = rest_time_control
            for part in path_parts:
                if part not in current_dict:
                    return jsonify({'success': False, 'message': f'参数 {param_name} 不存在'})
                current_dict = current_dict[part]
            return jsonify({'success': True, 'value': current_dict})
        else:
            return jsonify({'success': False, 'message': f'参数类型 {param_type} 不存在'})
    except Exception as e:
        return jsonify({'success': False, 'message': f'获取参数失败: {str(e)}'})

@views_page.route('/shift_assignments_page')
def shift_assignments_page():
    """护理员排班表页面"""
    # 获取最新的排班结果
    latest_assignments = ShiftAssignment.query.order_by(
        ShiftAssignment.shift_date.desc()
    ).limit(50).all()

    return render_template('shift_assignments.html', assignments=latest_assignments)

@views_page.route('/schedule_results_page')
def schedule_results_page():
    """照护计划总表页面"""
    # 获取最新的排班结果
    latest_results = ScheduleResult.query.order_by(
        ScheduleResult.schedule_date.desc()
    ).limit(20).all()

    return render_template('schedule_results.html', results=latest_results)

@views_page.route('/time_slots_page')
def time_slots_page():
    """照护计划分表页面"""
    # 获取最新的时间段
    latest_slots = TimeSlot.query.order_by(
        TimeSlot.schedule_date.desc()
    ).limit(100).all()

    return render_template('time_slots.html', slots=latest_slots)

@views_page.route('/import_excel_page')
def import_excel_page():
    """导入Excel页面"""
    # 获取当前日期，作为默认排班日期
    today = date.today()
    return render_template('import_excel.html', today=today)

@views_page.route('/download_excel_template')
def download_excel_template():
    """下载Excel模板"""
    # 创建Excel文件
    output = io.BytesIO()
    writer = pd.ExcelWriter(output, engine='xlsxwriter')
    
    # 护理员信息表
    df_caregivers = pd.DataFrame({
        'caregiver_id': [1, 2, 3],
        'name': ['张三', '李四', '王五'],
        'role': ['护士', '护工', '护理员'],
        'skill_level': [3, 2, 1],
        'morning_preference': [0.8, 0.5, 0.2],  # 偏好系数，0-1之间
        'afternoon_preference': [0.2, 0.5, 0.8],
        'night_preference': [0.1, 0.2, 0.5]
    })
    df_caregivers.to_excel(writer, sheet_name='护理员信息', index=False)
    
    # 老人信息表
    df_elders = pd.DataFrame({
        'elder_id': [1, 2, 3],
        'name': ['张老', '李老', '王老'],
        'age': [75, 82, 68],
        'care_level': [3, 2, 1],  # 照护等级
        'special_needs': ['行动不便', '需要特殊饮食', '听力障碍']
    })
    df_elders.to_excel(writer, sheet_name='老人信息', index=False)
    
    # 班次信息表
    df_shifts = pd.DataFrame({
        'shift_mode': [1, 2, 3],
        'shift_name': ['早班', '中班', '晚班'],
        'start_time': ['06:00', '14:00', '22:00'],
        'end_time': ['14:00', '22:00', '06:00']
    })
    df_shifts.to_excel(writer, sheet_name='班次信息(可选)', index=False)
    
    # 创建说明表
    workbook = writer.book
    worksheet = workbook.add_worksheet('使用说明')
    
    # 添加说明内容
    instructions = [
        '使用说明：',
        '1. 护理员信息表：填写护理员基本信息',
        '   - caregiver_id: 护理员ID，唯一标识',
        '   - name: 护理员姓名',
        '   - role: 护理员角色',
        '   - skill_level: 技能等级，1-3，3为最高',
        '   - morning/afternoon/night_preference: 班次偏好系数，0-1，1为最高',
        '',
        '2. 老人信息表：填写老人基本信息',
        '   - elder_id: 老人ID，唯一标识',
        '   - name: 老人姓名',
        '   - age: 老人年龄',
        '   - care_level: 照护等级，1-3，3为最高',
        '   - special_needs: 特殊需求',
        '',
        '3. 班次信息表（可选）：',
        '   - 如果不填写，系统将使用默认班次设置',
        '   - shift_mode: 班制模式，1-3',
        '   - shift_name: 班次名称',
        '   - start_time/end_time: 班次开始/结束时间',
        '',
        '注意：',
        '- 请不要修改表头',
        '- 请确保ID字段唯一',
        '- 时间格式为24小时制，如06:00'
    ]
    
    for i, instruction in enumerate(instructions):
        worksheet.write(i, 0, instruction)
    
    # 调整列宽
    worksheet.set_column(0, 0, 60)
    
    # 保存Excel文件
    writer.close()
    
    # 将IO缓冲区的位置重置到开始
    output.seek(0)
    
    # 发送文件
    return send_file(
        output,
        mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
        as_attachment=True,
        download_name='护理排班模板.xlsx'
    )

def update_param(param_dict, param_name, param_value):
    """更新参数字典中的参数值"""
    if param_name not in param_dict:
        raise ValueError(f"参数 {param_name} 不存在")

    # 尝试转换参数值为正确的类型
    old_value = param_dict[param_name]
    if isinstance(old_value, bool):
        if param_value.lower() == 'true':
            param_dict[param_name] = True
        elif param_value.lower() == 'false':
            param_dict[param_name] = False
        else:
            raise ValueError(f"布尔参数 {param_name} 的值必须是 'true' 或 'false'")
    elif isinstance(old_value, int):
        param_dict[param_name] = int(param_value)
    elif isinstance(old_value, float):
        param_dict[param_name] = float(param_value)
    elif isinstance(old_value, str):
        param_dict[param_name] = param_value
    elif isinstance(old_value, list):
        # 尝试解析列表
        try:
            # 首先尝试解析为JSON
            param_dict[param_name] = json.loads(param_value)
        except json.JSONDecodeError:
            # 如果不是有效的JSON，则尝试按逗号分隔
            if ',' in param_value:
                param_dict[param_name] = [item.strip() for item in param_value.split(',') if item.strip()]
            elif param_value:
                # 如果只有一个值，则创建只包含该值的列表
                param_dict[param_name] = [param_value]
            else:
                # 如果值为空，则创建空列表
                param_dict[param_name] = []
    elif isinstance(old_value, dict):
        # 尝试解析字典
        try:
            param_dict[param_name] = json.loads(param_value)
        except json.JSONDecodeError:
            raise ValueError(f"字典参数 {param_name} 的值必须是有效的JSON")
    else:
        # 其他类型，直接赋值
        param_dict[param_name] = param_value

def update_nested_param(param_dict, param_path, param_value):
    """更新嵌套参数字典中的参数值"""
    # 解析参数路径
    path_parts = param_path.split('.')

    # 递归查找参数
    current_dict = param_dict
    for i, part in enumerate(path_parts):
        if i == len(path_parts) - 1:
            # 最后一个部分是参数名
            if part not in current_dict:
                raise ValueError(f"参数 {param_path} 不存在")

            # 更新参数值
            old_value = current_dict[part]
            if isinstance(old_value, bool):
                if param_value.lower() == 'true':
                    current_dict[part] = True
                elif param_value.lower() == 'false':
                    current_dict[part] = False
                else:
                    raise ValueError(f"布尔参数 {param_path} 的值必须是 'true' 或 'false'")
            elif isinstance(old_value, int):
                current_dict[part] = int(param_value)
            elif isinstance(old_value, float):
                current_dict[part] = float(param_value)
            elif isinstance(old_value, str):
                current_dict[part] = param_value
            elif isinstance(old_value, list):
                # 尝试解析列表
                try:
                    # 首先尝试解析为JSON
                    current_dict[part] = json.loads(param_value)
                except json.JSONDecodeError:
                    # 如果不是有效的JSON，则尝试按逗号分隔
                    if ',' in param_value:
                        current_dict[part] = [item.strip() for item in param_value.split(',') if item.strip()]
                    elif param_value:
                        # 如果只有一个值，则创建只包含该值的列表
                        current_dict[part] = [param_value]
                    else:
                        # 如果值为空，则创建空列表
                        current_dict[part] = []
            elif isinstance(old_value, dict):
                # 尝试解析字典
                try:
                    current_dict[part] = json.loads(param_value)
                except json.JSONDecodeError:
                    raise ValueError(f"字典参数 {param_path} 的值必须是有效的JSON")
            else:
                # 其他类型，直接赋值
                current_dict[part] = param_value
        else:
            # 中间部分是字典
            if part not in current_dict or not isinstance(current_dict[part], dict):
                raise ValueError(f"参数路径 {param_path} 无效")

            current_dict = current_dict[part]

def update_config_file():
    """更新配置文件"""
    # 获取配置文件路径
    config_file_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'config_params.py')

    # 读取配置文件内容
    with open(config_file_path, 'r', encoding='utf-8') as f:
        content = f.read()

    # 更新params字典
    content = update_dict_in_file(content, 'params', params)

    # 更新shift_config字典
    content = update_dict_in_file(content, 'shift_config', shift_config)

    # 更新three_shift_params字典
    content = update_dict_in_file(content, 'three_shift_params', three_shift_params)

    # 更新shift_control字典
    content = update_dict_in_file(content, 'shift_control', shift_control)

    # 更新shift_mode_config字典
    content = update_dict_in_file(content, 'shift_mode_config', shift_mode_config)

    # 更新rest_time_control字典
    content = update_dict_in_file(content, 'rest_time_control', rest_time_control)

    # 写入配置文件
    with open(config_file_path, 'w', encoding='utf-8') as f:
        f.write(content)

    # 重新加载配置模块
    importlib.reload(sys.modules['config_params'])

def update_dict_in_file(content, dict_name, dict_value):
    """更新文件中的字典"""
    # 查找字典定义的起始位置
    start_pattern = re.compile(f"{dict_name}\\s*=\\s*{{")
    start_match = start_pattern.search(content)
    if not start_match:
        raise ValueError(f"在配置文件中找不到 {dict_name} 字典的定义")

    start_pos = start_match.start()

    # 查找字典定义的结束位置
    # 这里使用一个简单的方法：从起始位置开始，计算花括号的嵌套层数
    end_pos = start_pos
    brace_count = 0
    in_string = False
    string_char = None

    for i in range(start_pos, len(content)):
        char = content[i]

        # 处理字符串
        if char in ('"', "'") and (i == 0 or content[i-1] != '\\'):
            if not in_string:
                in_string = True
                string_char = char
            elif char == string_char:
                in_string = False
                string_char = None

        # 只有在不在字符串中时才计算花括号
        if not in_string:
            if char == '{':
                brace_count += 1
            elif char == '}':
                brace_count -= 1
                if brace_count == 0:
                    end_pos = i + 1
                    break

    # 格式化字典为字符串
    dict_str = format_dict(dict_value)

    # 替换字典定义
    new_content = content[:start_pos] + f"{dict_name} = {dict_str}" + content[end_pos:]

    return new_content

def format_dict(d, indent=0):
    """格式化字典为字符串"""
    result = "{\n"
    for key, value in d.items():
        result += " " * (indent + 4)

        # 格式化键
        if isinstance(key, str):
            result += f'"{key}"'
        else:
            result += str(key)

        result += ": "

        # 格式化值
        if isinstance(value, dict):
            result += format_dict(value, indent + 4)
        elif isinstance(value, list):
            result += format_list(value, indent + 4)
        elif isinstance(value, str):
            result += f'"{value}"'
        elif isinstance(value, bool):
            result += str(value)
        elif value is None:
            result += "None"
        else:
            result += str(value)

        result += ",\n"

    result += " " * indent + "}"
    return result

def format_list(lst, indent=0):
    """格式化列表为字符串"""
    if not lst:
        return "[]"

    result = "[\n"
    for item in lst:
        result += " " * (indent + 4)

        # 格式化项
        if isinstance(item, dict):
            result += format_dict(item, indent + 4)
        elif isinstance(item, list):
            result += format_list(item, indent + 4)
        elif isinstance(item, str):
            result += f'"{item}"'
        elif isinstance(item, bool):
            result += str(item)
        elif item is None:
            result += "None"
        else:
            result += str(item)

        result += ",\n"

    result += " " * indent + "]"
    return result

def init_app(app):
    """初始化前端页面蓝图"""
    app.register_blueprint(views_page, url_prefix='/page')
